home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
vol_100
/
183_01
/
gray.c
< prev
next >
Wrap
Text File
|
1980-01-01
|
7KB
|
181 lines
/* Some useful bit manipulation functions inspired by the article
* "Binary Magic Numbers" by Edwin E. Freed in DDJ #78, April 1983.
* by Dale Wilson, 1983 --- placed in the Public Domain
*
* These functions were written so thay may be directly translated
* into assembly language for most computers.
*
* These functions were tested on a Zenith 100 computer using the
* C86 compiler from Computer Innovations, Inc.
*
* --------------------------------------------------------------------
* This code was keyboarded into an IBM PC from the March'84 (#89) issue
* of Dr. Dobb's Journal. The code was tested then on the IBM PC using
* the C86 compiler from Computer Innovations, Inc. The output test
* results checked out with the sample output in the article.
* --------------------------------------------------------------------
*/
#include <stdio.h>
#define TRUE 1 /* true */
#define FALSE 0 /* false */
#define CNTLZ 26 /* ms-dos eof */
#define N 16 /* bits per "word" */
#define V 4 /* log 2 of N */
/* Since C does not have binary constants, the binary magic numbers are
* expressed below in hexadecimal. B from Freed's article is devided
* into b1 and b2 since ther was no good reason to have them in the
* same array.
*/
unsigned int b1[V] = { 0x5555, 0x3333, 0x0f0f, 0x00ff };
unsigned int b2[V] = { 0xaaaa, 0xcccc, 0xf0f0, 0xff00 };
/* Converting binary numbers to Gray code is so simple that it may
* be best defined as a macro rather than a function.
*/
#define binary_to_Gray(x) (x ^ x >> 1) /* X exclusive or X shifted right 1 */
/* MAIN rutine to test the functions.
* Numbers ( entered in hexadecimal ) will be used as aguments in each
* of the functions. As an additional check, the binary number resulting
* from the Gray_to_binary function will be converted back to Gray code --
* which shold result in the original number.
*/
main(argc,argv) int argc; char *argv[];
{ unsigned int r,i;
int c;
while (TRUE)
{
printf("Enter number : ");
fscanf(stdin,"%x",&i); /* read a hexadecimal */
while((c=getchar()) != '\n') /* discard end of line */
if(c == EOF || c == CNTLZ) /* except on end of file */
exit(); /* quit */
printf("low clear bit: %d\n", low_clear_bit(i));
printf("high set bit : %d\n", hi_set_bit(i));
printf("side sum : %d\n", side_sum(i));
printf("parity : %d\n", parity(i));
r = Gray_to_binary(i);
printf("Gray code : 0x%04x\n", r);
printf("GTB to Binary: 0x%04x\n", binary_to_Gray(r));
printf("Reversed bits: 0x%04x\n", reverse_bits(i));
putchar('\n'); /* leave a blank line between */
}
}
/* This function returns the bit number of the lowest bit in the word
* which is clear (zero). The least significant bit is numbered 0, the
* bit to the left of that, 1, and so on...
* A minus 1 is returned for words in which all bits are on.
* The time to execute this function is proportional to V which is
* log2 of the number of bits in a word.
* Note that the function low_set_bit may be created by complementing the
* argument and calling low_clear_bit.
*/
low_clear_bit(value) unsigned int value;
{ unsigned int temp;
int i, result;
if((value = ~value) == 0) /* complement, test for zero */
result = -1; /* zero means no clear bits */
else
{ result = 0;
for(i = V-1; i >= 0; i--)
{ result <<= 1; /* make space for next bit */
temp = value & b1[i]; /* test using magic numbers */
if(temp == 0)
result |= 1; /* next bit of result is 1 */
else
value = temp; /* discard disqualified bits */
}
}
return(result);
}
/* This function returns the bit number of the highest bit in the word
* which is set (one). The least significant bit is numbered 0, the
* bit to the left of that, 1, and so on ...
* A minus 1 is returned for words in which all bits are off.
* The time to execute this function is proportinal to V which is
* log2 of the number of bits in a word.
* Note that the function high_clear_bit may be created by complementing the
* argument and calling high_set_bit.
*/
hi_set_bit(value) unsigned int value;
{ unsigned int temp;
int result, i;
if(value == 0) /* if no bits are on */
result = -1; /* return that info */
else
{ result = 0;
for(i = V-1; i >= 0; i--)
{ result <<= 1; /* space for next bit */
temp = value & b2[i];
if(temp != 0)
{ result |= 1; /* next bit is one */
value = temp; /* discarded unneeded bits */
}
}
}
return(result);
}
/* This function returns a count of the number of bits which are on in a
* word. It executes in a time porportional to V, the log base 2 of the
* number of bits in a word.
* Note that a count of the number of zero bits in the word may be found
* by complementing the value and calling side_sum.
*/
side_sum(value) unsigned int value;
{ int i;
unsigned int s;
s = 1;
for(i=0; i<V; i++) /* use magic in reverse order */
{ value = (value & b1[i]) + ((value >> s) & b1[i]);
s <<= 1; /* generate the powers of two on the fly */
}
return(value);
}
/* This function converts a number expressed in Gray code to the
* equivalent binary number. It executes in time proportional to the
* log base 2 of the number of bits in the word.
*/
Gray_to_binary(value) unsigned int value;
{ unsigned int s;
for(s = N >> 1; s != 0; s >>= 1)
{ value ^= value >> s;
}
return(value);
}
/* This function returns the parity of a word--that is, it returns a zero
* if the number of one bits in the word is even, and a one if the number
* of one bits in the word is odd. The low order bit of the results of
* Gray_to_binary and side_sum both have this property, so isolating this
* bit gives the desired result. Gray_to_binary was selected since it is
* a faster function that side_sum.
*/
parity(value) unsigned int value;
{
return(Gray_to_binary(value) & 1); /* buld on previous work */
}
/* This function reverses the bits in a word. Strangly enough, this turns
* out to be a very useful function to have available. Note that this function
* works only on functions with word lengths which are powers of 2.
*/
reverse_bits(value) unsigned int value;
{ unsigned int s,i;
s = 1; /* s provides the powers of 2 */
for (i=0; i<V; i++)
{ value = ((value << s) & b2[i]) | ((value >> s) & b1[i]);
s <<= 1;
}
return(value);
}